import { CheckUtil } from './check';

/** 日期相关包 **/
export const DateUtil = {
  /**
   * 时间格式化
   * @example getFormat(new Date("2021-06-01"), "yyyy-MM-dd hh:mm:ss") => "2021-06-01 08:00:00"
   * @param format
   * @param date
   * @returns {string|Date}
   */
  getFormat(date = new Date(), format = 'yyyy-MM-dd hh:mm:ss') {
    if (!CheckUtil.isLikeDate(date) || !CheckUtil.isString(format)) {
      return '';
    }
    date = new Date(date);

    const keyMap = {
      y: date.getFullYear(),
      M: date.getMonth() + 1,
      d: date.getDate(),
      h: date.getHours(),
      m: date.getMinutes(),
      s: date.getSeconds(),
      w: date.getDay(),
      A: date.getHours() >= 12 ? 'PM' : 'AM', // 判断是 AM 还是 PM
    };

    Object.keys(keyMap).forEach((key) => {
      format = format.replace(new RegExp(`${key}+`, 'g'), function (s) {
        const value = String(keyMap[key]);
        return key === 'y'
          ? ('0000' + value).slice(-s.length)
          : key === 'w'
          ? '星期' + '日一二三四五六'[value]
          : ('00' + value).slice(-Math.max(value.length, s.length));
        // : ("" + value).padStart(Math.max(value.length, s.length), "0"); // str.padStart(2, "0"), ES6语法，str位数不足2位，前面补0
      });
    });

    return format;
  },

  /**
   * 获取俩个时间比较后的友好显示（date1 与 date2的时差）
   * @param date1
   * @param date2
   * @returns {{label: null, value: (string|Date)}|null}
   */
  getFriendlyDateByCompare(date1, date2 = new Date()) {
    if (!CheckUtil.isLikeDate(date1) || !CheckUtil.isLikeDate(date2)) {
      return Object.create(null);
    }
    date1 = new Date(date1);
    date2 = new Date(date2);

    const res = {
      label: null, // 友好的显示值
      value: this.getFormat(date1), // 日期格式化值
    };

    let val = date2 - date1;
    let text = '前';
    if (val < 0) {
      val = -val;
      text = '后';
    }

    const valDate = new Date(val);
    const initDate = new Date(0); // 日期初始值，1970-01-01 08:00:00
    const year = valDate.getFullYear() - initDate.getFullYear();
    const month = valDate.getMonth() - initDate.getMonth();
    const date = valDate.getDate() - initDate.getDate();
    const hours = valDate.getHours() - initDate.getHours();
    const minutes = valDate.getMinutes() - initDate.getMinutes();
    // let seconds = valDate.getSeconds() - initDate.getSeconds();

    if (year > 0) {
      res.label = `${year}年${text}`;
    } else if (month > 0) {
      res.label = `${month}个月${text}`;
    } else if (date > 0) {
      res.label = `${date}天${text}`;
    } else if (hours > 0) {
      res.label = `${hours}小时${text}`;
    } else if (minutes > 0) {
      res.label = `${minutes}分钟${text}`;
    } else {
      res.label = val < 0 ? '' : '刚刚';
    }

    return res;
  },

  /**
   * 获取俩个时间比较后的友好显示（date1 与 date2的时差）
   * @param date1
   * @param date2
   * @returns {{label: null, value: (string|Date)}|null}
   */
  getFriendlyDate(date1, date2 = new Date()) {
    if (!CheckUtil.isLikeDate(date1) || !CheckUtil.isLikeDate(date2)) {
      return Object.create(null);
    }
    date1 = new Date(date1);
    date2 = new Date(date2);

    const res = {
      label: '', // 友好的显示值
      value: this.getFormat(date1), // 日期格式化值
    };

    const valDate = new Date(Math.abs(date2 - date1));
    const initDate = new Date(0); // 日期初始值，1970-01-01 08:00:00
    const year = valDate.getFullYear() - initDate.getFullYear();
    const month = valDate.getMonth() - initDate.getMonth();
    const date = valDate.getDate() - initDate.getDate();
    const hours = valDate.getHours() - initDate.getHours();
    const minutes = valDate.getMinutes() - initDate.getMinutes();
    // let seconds = valDate.getSeconds() - initDate.getSeconds();

    if (year > 0) {
      res.label += `${year}年`;
    }
    if (month > 0) {
      res.label += `${month}个月`;
    }
    if (date > 0) {
      res.label += `${date}天`;
    }
    if (hours > 0) {
      res.label += `${hours}小时`;
    }
    if (minutes > 0) {
      res.label += `${minutes}分钟`;
    }

    return res;
  },

  /**
   * 获取俩个时间比较后的友好显示（date1 与 date2的时差差几天）
   * @param date1
   * @param date2
   * @returns {{label: null, value: (string|Date)}|null}
   */
  getFriendlyDateByCompareDay(date1, date2 = new Date()) {
    if (!CheckUtil.isLikeDate(date1) || !CheckUtil.isLikeDate(date2)) {
      return Object.create(null);
    }
    date1 = new Date(this.getFormat(date1, 'yyyy-MM-dd 00:00:00'));
    date2 = new Date(this.getFormat(date2, 'yyyy-MM-dd 23:59:59'));

    let res;

    let val = date2 - date1;

    const valDate = new Date(val);
    const initDate = new Date(0); // 日期初始值，1970-01-01 08:00:00
    const date = valDate.getDate() - initDate.getDate();

    if (date > 0) {
      res = date;
    } else {
      res = 1;
    }
    return res;
  },

  /**
   * 获取指定月的天数
   * @param date
   * @returns {number}
   */
  getDaysOfMonth(date = new Date()) {
    if (!CheckUtil.isLikeDate(date)) {
      return 0;
    }
    date = new Date(date);

    return new Date(date.getFullYear(), date.getMonth(), 0).getDate();
  },

  /**
   * 获取指定日期之前天数的日期
   * @param days
   * @param date
   * @returns {Date}
   */
  getDateAgo(days = 0, date = new Date()) {
    if (!CheckUtil.isNumber(days) && !CheckUtil.isLikeDate(date)) {
      return new Date();
    }
    
    date = new Date(date);

    date.setDate(date.getDate() - days);
    return new Date(date);
  },

  /**
   * 获取指定日期之后天数的日期
   * @param days
   * @param date
   * @returns {Date}
   */
  getDayLater(days = 0, date = new Date()) {
    if (!CheckUtil.isNumber(days) || !CheckUtil.isLikeDate(date)) {
      return new Date();
    }
    date = new Date(date);

    date.setDate(date.getDate() + days);
    return new Date(date);
  },

  /**
   * 获取指定日期之前月数的日期
   * @param months
   * @param date
   * @returns {Date}
   */
  getMonthAgo(months = 0, date = new Date()) {
    if (!CheckUtil.isNumber(months) || !CheckUtil.isLikeDate(date)) {
      return new Date();
    }
    date = new Date(date);

    date.setMonth(date.getMonth() - months);
    return new Date(date);
  },

  /**
   * 取指定日期之后月数的日期
   * @param months <Number>
   * @param date <Date>
   * @returns {Date}
   */
  getMonthLater(months = 0, date = new Date()) {
    if (!CheckUtil.isNumber(months) || !CheckUtil.isLikeDate(date)) {
      return new Date();
    }
    date = new Date(date);

    date.setMonth(date.getMonth() + months);
    return new Date(date);
  },

  /**
   * 获取指定日期是星期几（中文）
   * @param date
   * @param lang
   * @returns {string}
   */
  getWeekDay(date = new Date(), lang = 'cn') {
    if (!CheckUtil.isLikeDate(date)) {
      return '';
    }
    date = new Date(date);

    let res;
    switch (lang) {
      case 'cn':
        res = '星期' + ['天', '一', '二', '三', '四', '五', '六'][date.getDay()];
        break;
      case 'en':
        res = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'][date.getDay()];
        break;
      default:
        break;
    }
    return res;
  },

  /**
   * 获取当前季度
   * @param date
   * @param lang
   * @returns {string}
   */
  getQuarter(date = new Date(), lang = 'cn') {
    if (!CheckUtil.isLikeDate(date)) {
      return '';
    }
    date = new Date(date);

    let res;
    switch (lang) {
      case 'cn':
        res = `第${['一', '二', '三', '四'][Math.floor(date.getMonth() / 3)]}季度`;
        break;
      case 'en':
        res = `the ${['one', 'two', 'three', 'four'][Math.floor(date.getMonth() / 3)]} quarter`;
        break;
      default:
        break;
    }
    return res;
  },

  /**
   * 根据日期获取该月的第一天和最后一天（注意 Browser 和 Node 环境 new Date(year, month)的差别）
   * @param date
   * @returns {{}|{endDate: Date, startDate: Date}}
   */
  getStartEndDateByMonth(date = new Date()) {
    if (!CheckUtil.isLikeDate(date)) {
      return {};
    }
    date = new Date(date);

    const year = date.getFullYear();
    const month = date.getMonth();

    // 注意：对于new Date(2021, 2)， 浏览器环境返回2021年3月第一天，Node环境返回2021年2月最后一天；
    let startDate, endDate;
    const oneDaySeconds = 1000 * 60 * 60 * 24;
    if (CheckUtil.isBrowser()) {
      startDate = new Date(year, month);
      endDate = new Date(new Date(year, month + 1) - oneDaySeconds);
    } else if (CheckUtil.isNode()) {
      startDate = new Date(new Date(year, month) + oneDaySeconds);
      endDate = new Date(year, month + 1);
    } else {
      return {};
    }

    endDate.setHours(23, 59, 59);
    return {
      startDate,
      endDate,
      formatStartDate: this.getFormat(startDate),
      formatEndDate: this.getFormat(endDate),
    };
  },

  /**
   * 根据年获取该年的第一天和最后一天（注意 Browser 和 Node 环境 new Date(year, month)的差别）
   * @returns {{}|{endDate: Date, startDate: Date}}
   * @param date
   */
  getStartEndDateByYear(date = new Date()) {
    if (!CheckUtil.isLikeDate(date)) {
      return {};
    }
    const year = new Date(date).getFullYear();

    let startDate, endDate;
    const oneDaySeconds = 1000 * 60 * 60 * 24;
    if (CheckUtil.isBrowser()) {
      startDate = new Date(year, 0);
      endDate = new Date(new Date(year + 1, 0) - oneDaySeconds);
    } else if (CheckUtil.isNode()) {
      startDate = new Date(new Date(year, 0) + oneDaySeconds);
      endDate = new Date(year + 1, 0);
    } else {
      return {};
    }

    endDate.setHours(23, 59, 59);
    return {
      startDate,
      endDate,
    };
  },

  /**
   * 获取本周的第一天和最后一天
   * @returns {{}|{endDate: Date, startDate: Date}}
   * @param date
   */
  getStartEndDateByWeek(date = new Date()) {
    if (!CheckUtil.isLikeDate(date)) {
      return {};
    }
    // 获取当前日期是本周的第几天
    let dayOfWeek = date.getDay();

    // 将日期设置为本周的第一天
    let startDate = new Date(date);
    //如果今天是周日进行处理
    startDate.setDate(date.getDate() - dayOfWeek + (dayOfWeek === 0 ? -6 : 1));

    // 将日期设置为本周的最后一天
    let endDate = new Date(date);
    //如果今天是周日进行处理
    endDate.setDate(date.getDate() + (dayOfWeek === 0 ? 0 : 7 - dayOfWeek));

    // 返回结果
    return {
      startDate,
      endDate,
      formatStartDate: this.getFormat(startDate),
      formatEndDate: this.getFormat(endDate),
    };
  },

  /**
   * 根据年月(0-11)获取该月天组成的数组，(2021, 7) => ["08-01", "08-02", ..., "08-31"]
   * @param year yyyy
   * @param month 0-11
   * @param includeMonth <是否返回格式为 MM-dd>
   * @param includeYear <是否返回格式为 yyyy-MM-dd>
   * @returns {any[]}
   */
  getDaysByMonth(year, month, includeMonth = true, includeYear = true) {
    let len;
    const oneDaySeconds = 1000 * 60 * 60 * 24;
    if (CheckUtil.isBrowser()) {
      len = new Date(new Date(year, month + 1) - oneDaySeconds).getDate();
    } else if (CheckUtil.isNode()) {
      len = new Date(year, month + 1).getDate();
    } else {
      return [];
    }

    const res = Array(len);
    const _month = String(month + 1).padStart(2, '0');
    for (let i = 0; i < len; i++) {
      res[i] = (includeYear ? year + '-' : '') + (includeMonth ? _month + '-' : '') + String(i + 1).padStart(2, '0');
    }

    return res;
  },

  /**
   * 根据年获取该年月天组成的数组，(2021) => [["01-01", ..., "01-31"], ..., ["12-01", ..., "12-31"]]
   * @param year
   * @returns {any[]}
   */
  getDaysByYear(year) {
    const res = [];
    for (let i = 0; i < 12; i++) {
      res[i] = this.getDaysByMonth(year, i);
    }

    return res;
  },

  /**
   * 根据年获取该年每月有多少天组成的数组，(2021) => []
   * @param year
   * @returns {any[]}
   */
  getMonthCountByYear(year) {
    const res = [];
    const oneDaySeconds = 1000 * 60 * 60 * 24;
    for (let i = 0; i < 12; i++) {
      let len;
      if (CheckUtil.isBrowser()) {
        len = new Date(new Date(year, i + 1) - oneDaySeconds).getDate();
      } else if (CheckUtil.isNode()) {
        len = new Date(year, i + 1).getDate();
      } else {
        return [];
      }
      res[i] = len;
    }

    return res;
  },
};
